﻿using CarArranger.Forms;
using CarArranger.Model;
using System;
using System.Windows.Forms;
using System.Linq;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace CarArranger
{
    public partial class CarArranger : Form
    {
        private Document _data = new Document();
        private Bitmap _map;

        public CarArranger()
        {
            InitializeComponent();
            MTypeSelect.SelectedIndex = 0;
            listView1.Font = Display.CurDisplay.Font;
            //Generater Test Data
            //_data.Yard = new Yard();
            //_data.Yard.Tracks.Add(new Track("12"));
            //_data.Yard.Tracks.Add(new Track("13"));
            //_data.Yard.Tracks.Add(new Track("14"));

            //_data.CarList = new CarList();
            //_data.CarList.Add(new CarGroup() { CarNum = 3, DestNum = 4 });
            //_data.CarList.Add(new CarGroup() { CarNum = 4, DestNum = 3 });
            //_data.CarList.Add(new CarGroup() { CarNum = 6, DestNum = 2 });
            //_data.CarList.Add(new CarGroup() { CarNum = 1, DestNum = 1 });
            //_data.CarList.PrimalTrack = _data.Yard.Tracks.First();

            //_data.InitStatus();
        }

        private void 站场设置ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LayoutSettingForm form = new LayoutSettingForm();
            DialogResult result = form.ShowDialog();
            if (result == DialogResult.OK)
            {
                _data.Yard = form.Yard;
                _data.CarList = null;
                _data.InitStatus();
                UpdateList();
                UpdateTrackSelect();
                MapView.Refresh();
            }
        }

        private void 待解编车列ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (_data.Yard != null)
            {
                EditCarList form = new EditCarList(_data.Yard);
                DialogResult result = form.ShowDialog();
                if (result == DialogResult.OK)
                {
                    _data.CarList = form.CarList;
                    _data.InitStatus();
                    UpdateList();
                    UpdateTrackSelect();
                    MapView.Refresh();
                }
            }
            else
            {
                MessageBox.Show("请先初始化车场！");
            }
        }

        /// <summary>
        /// 绘制调车状态
        /// </summary>
        /// <param name="map"></param>
        /// <param name="display"></param>
        /// <param name="doc"></param>
        public void DrawMap(Bitmap map, Display display, Document doc)
        {
            Graphics xGraph = Graphics.FromImage(map);
            xGraph.Clear(Color.White);
            xGraph.SmoothingMode = display.TrainLineSmoothingMode;

            if (_data.Yard == null) return;
            //画调车线
            float xWidth = 0;
            foreach (Track track in _data.Yard.Tracks)
            {
                xWidth = System.Math.Max(xWidth, xGraph.MeasureString(track.Name, display.Font).Width);
            }

            float xTrackLength = (map.Width - display.Left - display.Right) / 2 - xWidth;//股道长度
            float xTrack = _data.Yard.IsLeftHandWork ? display.Left + map.Width / 2 + xWidth : display.Left + xWidth;
            float xString = xTrack - xWidth;
            float yTrack = (map.Height - display.Top - display.Bottom) / (_data.Yard.Tracks.Count() + 1);
            float y = display.Top + yTrack;
            foreach (Track t in _data.Yard.Tracks)
            {
                float yString = xGraph.MeasureString(t.Name, display.Font).Height / 2;
                xGraph.DrawLine(display.Pen, xTrack, y, xTrack + xTrackLength, y);
                xGraph.DrawString(t.Name, display.Font, Brushes.Black, xTrack, y - yString, new StringFormat(StringFormatFlags.DirectionRightToLeft));
                y += yTrack;
            }

            //画牵出线
            float xStringWidth = xGraph.MeasureString("牵出线", display.Font).Width;
            float xTransferTrack = _data.Yard.IsLeftHandWork ? display.Left + xStringWidth : display.Left + map.Width / 2 + xStringWidth;
            float xTransferLength = (map.Width - display.Left - display.Right) / 2 - xStringWidth;
            float yTransferTrack = (map.Height - display.Top - display.Bottom) / 2;
            float yTransferString = xGraph.MeasureString("牵出线", display.Font).Height / 2;
            xGraph.DrawLine(display.Pen, xTransferTrack, yTransferTrack, xTransferTrack + xTransferLength, yTransferTrack);
            xGraph.DrawString("牵出线", display.Font, Brushes.Black, xTransferTrack, yTransferTrack - yTransferString, new StringFormat(StringFormatFlags.DirectionRightToLeft));

            if (_data.CarList == null) return;

            //画调车线车组
            y = display.Top + yTrack;
            foreach (Track t in _data.Yard.Tracks)
            {
                float xCar = xTrack;
                foreach (CarGroup cg in _data.TrackStatus[t])
                {
                    string name = display.IsFullDisplayed ? cg.ToString():cg.DestNum.ToString();
                    float carGroupWidth = xGraph.MeasureString(name, display.Font).Width + 2 * display.Margin;
                    float carGroupHeight = xGraph.MeasureString(name, display.Font).Height + 2 * display.Margin;                 
                    xGraph.DrawRectangle(display.Pen, xCar, y - carGroupHeight, carGroupWidth, carGroupHeight);
                    xGraph.DrawString($"{name}", display.Font, Brushes.Black, xCar, y - carGroupHeight + display.Margin);
                    xCar += carGroupWidth;
                }
                y += yTrack;
            }

            //画牵出线车组
            float xTransferCar = xTransferTrack;
            foreach (CarGroup cg in _data.TransferTrackStatus)
            {
                string name = display.IsFullDisplayed ? cg.ToString() : cg.DestNum.ToString();
                float carGroupWidth = xGraph.MeasureString(name, display.Font).Width + 2 * display.Margin;
                float carGroupHeight = xGraph.MeasureString(name, display.Font).Height + 2 * display.Margin;
                xGraph.DrawRectangle(display.Pen, xTransferCar, yTransferTrack - carGroupHeight, carGroupWidth, carGroupHeight);
                xGraph.DrawString($"{name}", display.Font, Brushes.Black, xTransferCar, yTransferTrack - carGroupHeight + display.Margin);
                xTransferCar += carGroupWidth;
            }
        }

        private void 重绘ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MapView.Refresh();
        }

        private void MapView_Paint(object sender, PaintEventArgs e)
        {
            _map = new Bitmap(Math.Max(1, MapView.Width), Math.Max(1, MapView.Height));
            DrawMap(_map, Display.CurDisplay, _data);
            e.Graphics.DrawImage(_map, PointF.Empty);
        }

        private void MapView_Resize(object sender, EventArgs e)
        {
            MapView.Refresh();
        }

        private void UpdateList()
        {
            listView1.Items.Clear();
            foreach (Movement mov in _data.Plan.Movements)
            {
                ListViewItem listViewItem = new ListViewItem();
                listViewItem.Text = mov.ToString();
                listViewItem.Tag = mov;
                this.listView1.Items.Add(listViewItem);
            }
        }

        private void UpdateTrackSelect()
        {
            TrackSelect.Items.Clear();
            if (_data.Yard != null)
            {
                foreach (Track track in _data.Yard.Tracks)
                {
                    TrackSelect.Items.Add(track.Name);
                }
            }
            TrackSelect.SelectedIndex = 0;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //Box -> Movement
            Track track = _data.Yard.Tracks.FirstOrDefault(i => i.Name == TrackSelect.Text);
            MovementType mType = MovementType.Pick;
            if (MTypeSelect.Text == "+")
            {
                mType = MovementType.Pick;
            }
            else if (MTypeSelect.Text == "-")
            {
                mType = MovementType.Drop;
            }
            int carGroupNum = (int)CarNumInput.Value;

            Movement mov = new Movement()
            {
                Track = track,
                MType = mType,
                CarGroupNum = carGroupNum
            };
            bool isApplied = _data.ApplyMovement(mov);
            if (isApplied)
            {
                _data.Plan.Movements.Add(mov);
                UpdateList();
                StaticsLabel.Text = $"调车钩={_data.Plan.MoveCount},调车程={_data.Plan.MoveLength}";
                MapView.Refresh();
            }
            else
            {
                MessageBox.Show("不可行的钩计划");
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //获取上一个mov
            if (_data.Plan.Movements.Count() <= 0) return;
            Movement mov = _data.Plan.Movements.Last();
            Movement rMov = new Movement()
            {
                Track = mov.Track,
                MType = mov.MType.Reverse(),
                CarGroupNum = mov.CarGroupNum
            };

            bool isApplied = _data.ApplyMovement(rMov);
            if (isApplied)
            {
                _data.Plan.Movements.RemoveAt(_data.Plan.Movements.Count() - 1);
                UpdateList();
                StaticsLabel.Text = $"调车钩={_data.Plan.MoveCount},调车程={_data.Plan.MoveLength}";
                MapView.Refresh();
            }
            else
            {
                MessageBox.Show("不可行的钩计划");
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            _data.InitStatus();
            UpdateList();
            StaticsLabel.Text = $"调车钩={_data.Plan.MoveCount},调车程={_data.Plan.MoveLength}";
            MapView.Refresh();
        }
    }

    public class Display
    {
        private static Display _display;
        public static Display CurDisplay
        {
            get
            {
                if(_display == null)
                {
                    _display = new Display();
                }
                return _display;
            }
        }

        public int Left = 10, Right = 10, Top = 10, Bottom = 10, Middle = 20, X = 0, Y = 0, MouseX = 0, MouseY = 0;
        public int MultipleX = 1, MultipleY = 1, HourBegin = 0, HourEnd = 24;
        public int Margin = 2;
        public float ScaleX, ScaleY;
        public bool Code = false, Track = true, Circle = false, TrainUp = true, TrainDown = true;
        public bool StationCode = true, StationTime = false;
        public Font Font = new Font("宋体", 20);
        public Pen Pen = new Pen(Color.Green, 1);
        public Brush Brush = new SolidBrush(Color.White);
        public SizeF Size = new SizeF();
        public SmoothingMode TrainLineSmoothingMode = SmoothingMode.AntiAlias;
        public SmoothingMode StationSmoothingMode = SmoothingMode.HighSpeed;
        public bool IsFullDisplayed;
    }
}
